﻿using Frogsoft.Data;
using Frogsoft.Domain.Permission;
using Frogsoft.Permission.Dtos;
using Frogsoft.Permission.ShareDtos;
using Frogsoft.Permission.Consts;
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace Frogsoft.Permission
{
    public class UserService
    {
        private MyContext _myContext;
        private UserManager<AppUser>? _userManager;
        private RoleManager<IdentityRole>? _roleManager;
        public UserService(MyContext myContext, UserManager<AppUser>? userManager, RoleManager<IdentityRole>? roleManager)
        {
            _myContext = myContext;
            _userManager = userManager;
            _roleManager = roleManager;
        }

        public List<AppUserDto> GetAll()
        {
            return _myContext.Users.Select(o => new AppUserDto { Id = o.Id, UserName = o.UserName, FullName = o.NormalizedUserName, Email = o.Email, Mobile = o.PhoneNumber, IsLock = o.LockoutEnabled }).ToList();
        }

        public AppUserDto GetByUserName(string userName)
        {
            return _myContext.Users.Select(o => new AppUserDto { Id = o.Id, UserName = o.UserName, FullName = o.NormalizedUserName, Email = o.Email, Mobile = o.PhoneNumber, IsLock = o.LockoutEnabled }).FirstOrDefault(x => x.UserName == userName);
        }

        public Result<List<AppUserDto>> GetAllPageing(int page, int limit)
        {
            var total = _myContext.Users.Count();
            var data = _myContext.Users.OrderByDescending(s => s.LastUpdated).Skip((page - 1) * limit).Take(limit).Select(o => new AppUserDto { Id = o.Id, UserName = o.UserName, FullName = o.NormalizedUserName, Email = o.Email, Mobile = o.PhoneNumber, IsLock = o.LockoutEnabled }).ToList();
            return new Result<List<AppUserDto>>(0, total, data);
        }

        public AppUserDto Create(AppUserDto appUserDto)
        {
            AppUser appUser = new AppUser();
            appUser.UserName = appUserDto.UserName;
            appUser.NormalizedUserName = appUserDto.FullName;
            appUser.Email = appUserDto.Email;
            appUser.LastUpdated = DateTime.Now;
            var result = _userManager.CreateAsync(appUser, appUserDto.Password).Result;
            if (result.Succeeded)
            {
                appUserDto.Password = "";
                return appUserDto;
            }
            else
            {
                throw new Exception("用户创建失败");
            }
        }

        public async Task Delete(string userName)
        {
            var user = await _userManager.FindByNameAsync(userName);
            var resut = await _userManager.DeleteAsync(user);            
        }

        public AppUserDto Update(AppUserDto appUserDto)
        {
            var user = _userManager.FindByNameAsync(appUserDto.UserName).Result;
            //user.NormalizedUserName = appUserDto.FullName;
            user.Email = appUserDto.Email;
            user.LastUpdated = DateTime.Now;
            var result = _userManager.UpdateAsync(user).Result;
            if (result.Succeeded)
            {
                appUserDto.Password = "";
                return appUserDto;
            }
            else
            {
                throw new Exception("用户更新失败");
            }
        }

        public async Task<AppUserRoleDto> GetUserRoleAsync(string userName)
        {
            var user = await _userManager.FindByNameAsync(userName);
            var roles = await _userManager.GetRolesAsync(user);
            var allRoles = await _roleManager.Roles.ToListAsync();

            var allItems = allRoles.Select(o => new AppUserRoleItemDto
            {
                title = o.Name,
                value = o.Id,
                Checked = false,
                disabled = false
            }).ToList();
            
            var query = from t1 in allRoles
                        join t2 in roles on t1.Name equals t2 into tmp
                        from grantRole in tmp.DefaultIfEmpty()
                        where grantRole is not null
                        select new string(t1.Id);
                        
            var grantItems = query.ToList();
            var result = new AppUserRoleDto(allItems, grantItems);
            return result;
        }

        public AppUserRoleDto GetUserRole(string userName)
        {
            var user = _userManager.FindByNameAsync(userName).Result;
            var roles = _userManager.GetRolesAsync(user).Result;
            var allRoles = _roleManager.Roles.ToList();
            var allItems = allRoles.Select(o => new AppUserRoleItemDto
            {
                title = o.Name,
                value = o.Id,
                Checked = false,
                disabled = false
            }).ToList();
            var query = from t1 in allRoles
                        join t2 in roles on t1.Name equals t2 into tmp
                        from grantRole in tmp.DefaultIfEmpty()
                        where grantRole is not null
                        select new string(t1.Id);
            var grantItems = query.ToList();
            var result = new AppUserRoleDto(allItems, grantItems);
            return result;
        }

        public void UpdateUserRole(string userName, List<AppUserRoleItemDto> appUserRoleDtos)
        {
            var user = _userManager.FindByNameAsync(userName).Result;
            var oldData = _myContext.UserRoles.Where(o => o.UserId == user.Id).ToList();
            var newData = appUserRoleDtos.Select(o => new IdentityUserRole<string> { UserId = user.Id, RoleId = o.value }).ToList();
            _myContext.UserRoles.RemoveRange(oldData);
            _myContext.UserRoles.AddRange(newData);
            _myContext.SaveChanges();
        }
    }
}
